package edu.albany.csi518.sick;

import java.util.Scanner;

/**
 *
 * @author John M. Lien
 */
public class Shell {

    private final static int DISEASE = 0;   //Disease Constant
    private final static int SYMPTOM = 1;   //Symptom Constant
    private final static int MENU = 2;      //Menu Constant
    private final static int HELP = 3;      //Help Constant
    private final static int EXIT = 4;      //Exit Constant
    private int chosen_value;               //Chosen Constant by user
    private boolean debugger;               //Boolean for determining whether or not to use debugger
    private final Scanner input;
    private final DiseaseSymptom disease_symptom;
    private final CalculateConfidence confidence;

    private String main_menu() {
        return "\n############## S.I.C.K ##############"
                + "\nInput 'Disease' to find symptoms related to a specific disease."
                + "\nInput 'Symptom' to find diseases related to your symptoms."
                + "\nInput 'Menu' for the main prompt."
                + "\nInput 'Help' to find information reguarding commands."
                + "\nInput 'Exit' to end the program.\n";
    }

    /**
     * Prompts the welcome screen to the user.
     */
    private void prompt_welcome() {
        this.chosen_value = -1;
        while (this.chosen_value < 0) {
            /* Keep prompting the user while the input is invalid */
            this.prompt_welcome_screen();
        }

        /* Self Explanatory */
        if (debugger) {
            switch (this.chosen_value) {
                case DISEASE:
                    System.out.println();
                    System.out.flush();
                    System.err.println("DEBUGGER: Using DISEASE Algorithm");
                    System.err.flush();
                    break;
                case SYMPTOM:
                    System.out.println();
                    System.out.flush();
                    System.err.println("DEBUGGER: Using SYMPTOM Algorithm");
                    System.err.flush();
                    break;
            }
        }
    }

    private void prompt_welcome_screen() {
        String var;
        System.out.println(this.main_menu());
        System.out.print("What would you like to do? ");
        var = this.getLine();   //Get the input from the user
        if (this.checkForDebugger(var)) {
            /* If there is a debug flag the set the debugger */
            var = var.substring(0, var.indexOf("-debug")).trim();
        }

        /* Try to determine which input the user gave */
        switch (var) {
            case "disease":
                this.setChosenValue(DISEASE);   //Disease Chosen
                break;
            case "symptom":
                this.setChosenValue(SYMPTOM);   //Symptom Chosen
                break;
            case "help":
                this.setChosenValue(HELP);      //Help Chosen
                break;
            case "exit":
                this.setChosenValue(EXIT);      //Exit Chosen
                this.endProgram();
            case "menu":
                this.setChosenValue(MENU);      //Menu Chosen
                break;
            default:
                /* Guess the user chose disease */
                if (var.startsWith("d")) {
                    System.out.print("\nDid you mean to type Disease?(y/n): ");
                    var = this.getLine();
                    if (this.isYes(this.yesOrNo(var))) {
                        this.setChosenValue(DISEASE);
                        this.checkForDebugger(var);
                    } else {
                        prompt_welcome_screen();
                    }
                } else {
                    /* Guess the user chose symptom */
                    if (var.startsWith("s")) {
                        System.out.print("\nDid you mean to type Symptom?(y/n): ");
                        var = this.getLine();
                        if (this.isYes(this.yesOrNo(var))) {
                            this.setChosenValue(SYMPTOM);
                            this.checkForDebugger(var);
                        } else {
                            prompt_welcome_screen();
                        }
                    } else {
                        /* Guess the user chose exit */
                        if (var.startsWith("e")) {
                            System.out.print("\nDid you mean to type Exit?(y/n): ");
                            var = this.getLine();
                            if (this.isYes(this.yesOrNo(var))) {
                                this.setChosenValue(EXIT);
                                this.checkForDebugger(var);
                            } else {
                                prompt_welcome_screen();
                            }
                        } else {
                            /* Guess the user chose help */
                            if (var.startsWith("h")) {
                                System.out.print("\nDid you mean to type Help?(y/n): ");
                                var = this.getLine();
                                if (this.isYes(this.yesOrNo(var))) {
                                    this.setChosenValue(HELP);
                                    this.checkForDebugger(var);
                                } else {
                                    prompt_welcome_screen();
                                }
                            } else {
                                /* Guess the user chose menu */
                                if (var.startsWith("m")) {
                                    System.out.print("\nDid you mean to type Menu?(y/n): ");
                                    var = this.getLine();
                                    if (this.isYes(this.yesOrNo(var))) {
                                        this.setChosenValue(HELP);
                                        this.checkForDebugger(var);
                                    } else {
                                        prompt_welcome_screen();
                                    }
                                } else {
                                    prompt_welcome_screen();
                                }
                            }
                        }
                    }
                }
        }
    }

    /**
     *
     * @param val Constant passed into the setter method
     */
    private void setChosenValue(int val) {
        this.chosen_value = val;
    }

    /**
     *
     * @param val Line inputted by user
     * @return returns true if the debugger is set.
     */
    private boolean checkForDebugger(String val) {
        if (val.endsWith("-debug") || val.endsWith("-debugger")) {
            if (this.debugger) {
                System.out.print("\nTurn debugger off?(y/n): ");
                if (this.isYes(this.yesOrNo(this.getLine()))) {
                    System.out.flush();
                    System.err.println("Debugger Deactivated");
                    System.err.flush();
                    this.debugger = false;
                    return false;
                }
            } else {
                System.out.print("\nTurn debugger on?(y/n): ");
                if (this.isYes(this.yesOrNo(this.getLine()))) {
                    System.out.flush();
                    System.err.println("Debugger Activated");
                    System.err.flush();
                    this.debugger = true;
                    return true;
                }
            }
        }
        if (val.contains("-debug on") || val.contains("-debugger on")) {
            if (this.debugger) {
                System.out.flush();
                System.err.println("Debugger Already Activated");
                System.err.flush();
            } else {
                System.out.flush();
                System.err.println("Debugger Activated");
                System.err.flush();
                this.debugger = true;
                return true;
            }
        }
        if (val.contains("-debug off") || val.contains("-debugger off")) {
            if (this.debugger) {
                System.out.flush();
                System.err.println("Debugger Deactivated");
                System.err.flush();
                this.debugger = true;
                return true;
            } else {
                System.out.flush();
                System.err.println("Debugger Not Deactivated");
                System.err.flush();
            }
        }
        return false;
    }

    /**
     *
     * @param val integer constant
     * @return returns true if the value passed into the method is 1.
     */
    private boolean isYes(int val) {
        return val == 1;
    }

    /**
     *
     * @param var String constant passed in by user
     * @return returns 1 if yes, 0 if no, -1 if other.
     */
    private int yesOrNo(String var) {
        switch (var.toLowerCase().trim()) {
            case "y":
                return 1;
            case "yes":
                return 1;
            case "n":
                return 0;
            case "no":
                return 0;
            default:
                return -1;
        }
    }

    /**
     * Request input from the user.
     *
     * @return return the input from the user.
     */
    private String getLine() {
        return input.nextLine().toLowerCase().trim();
    }

    /**
     * Interact with the user to gain input.
     */
    private void interact_with_user() {
        while (true) {
            switch (this.chosen_value) {
                case DISEASE:
                    System.out.println("\nPlease enter a disease you would like to know more about");
                    System.out.print("DISEASE > ");
                    if (this.disease_symptom.analyzeInput(this.getLine(), this.debugger, true)) {
                        break; //Invalid Input
                    }
                    System.out.println();
                    this.disease_symptom.printDiseases();
                    System.out.println("\nWhich diseases would you like to know more about? \nplease enter the corresponding numbers from the list above (seperated by space). ");
                    System.out.println("For information on all the above diseases type \"all\"");
                    System.out.println("For information on non of the above just press the ENTER button.\n");
                    System.out.print("DISEASE NUMBERS> ");
                    this.confidence.printChosenDiseases(this.getLine());
                    break;
                case SYMPTOM:
                    System.out.println("\nPlease enter your list of symptoms (seperated by space)");
                    System.out.print("SYMPTOMS > ");
                    if (this.disease_symptom.analyzeInput(this.getLine(), this.debugger, false)) {
                        break; //Invalid Input
                    }
                    System.out.println();
                    System.err.flush();
                    this.disease_symptom.printRankedSymptoms();
                    System.out.flush();
                    System.err.flush();
                    System.out.println("\nIf any of the above symptoms also apply to you, \nplease enter the corresponding numbers from the list above (seperated by space). ");
                    System.out.println("If not, then just press the ENTER button.\n");
                    System.out.print("SYMPTOMS NUMBERS> ");
                    System.out.flush();
                    System.err.flush();
                    this.confidence.calculateConfidence(this.getLine());
                    System.out.println();
                    System.out.flush();
                    System.err.flush();
                    this.confidence.printCalculatedConfidence();
                    System.out.flush();
                    System.err.flush();
                    break;
                case MENU:
                    System.out.println(this.main_menu());
                    break;
                case EXIT:
                    this.endProgram();
            }
            System.out.print("\nRun Another Query?(y/n): ");
            if (this.isYes(this.yesOrNo(this.getLine()))) {
                this.prompt_welcome();
            } else {
                this.endProgram();
            }
        }
    }

    private void endProgram() {
        this.input.close();
        System.out.println("\nProgram Ended Successfully");
        System.out.flush();
        System.exit(0);
    }

    /**
     * Initiate the shell.
     */
    public void startShell() {
        prompt_welcome();
        interact_with_user();
    }

    /* Constructor */
    public Shell() {
        this.disease_symptom = new DiseaseSymptom();
        this.confidence = new CalculateConfidence(this.disease_symptom);
        this.input = new Scanner(System.in);
        this.debugger = false;
    }
}
